#ifdef __linux__
#include "../math/polygon.h"
#include <dlfcn.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

// 动态链接库路径
#define LIB_CACULATE_PATH "../lib/libmath.so"

// 函数指针
typedef int (*CAC_FUNC)(int, int);

int main() {
  void *handle;
  char *error;
  CAC_FUNC cac_func = NULL;

  // 打开动态链接库
  handle = dlopen(LIB_CACULATE_PATH, RTLD_LAZY);
  if (!handle) {
    fprintf(stderr, "%s\n", dlerror());
    exit(EXIT_FAILURE);
  }

  // 清除之前存在的错误
  dlerror();

  // 获取一个函数
  *(void **)(&cac_func) = dlsym(handle, "add");
  if ((error = dlerror()) != NULL) {
    fprintf(stderr, "%s\n", error);
    exit(EXIT_FAILURE);
  }
  printf("add: %d\n", (*cac_func)(2, 7));

  cac_func = (CAC_FUNC)dlsym(handle, "sub");
  printf("sub: %d\n", cac_func(9, 2));

  cac_func = (CAC_FUNC)dlsym(handle, "mul");
  printf("mul: %d\n", cac_func(3, 2));

  cac_func = (CAC_FUNC)dlsym(handle, "dvd");
  printf("div: %d\n", cac_func(8, 2));

  // 关闭动态链接库
  dlclose(handle);

  //*************** c++ ***************//

  void *triangle = dlopen(LIB_CACULATE_PATH, RTLD_LAZY);

  // load the symbols
  create_t *create_triangle = (create_t *)dlsym(triangle, "create");
  const char *dlsym_error = dlerror();
  if (dlsym_error) {
    std::cerr << "Cannot load symbol create: " << dlsym_error << '\n';
    return 1;
  }
  destroy_t *destroy_triangle = (destroy_t *)dlsym(triangle, "destroy");
  dlsym_error = dlerror();
  if (dlsym_error) {
    std::cerr << "Cannot load symbol destroy: " << dlsym_error << '\n';
    return 1;
  }
  // create an instance of the class
  polygon *poly = create_triangle();
  // use the class
  poly->set_side_length(7);
  std::cout << "The area is: " << poly->area() << '\n';
  // destroy the class
  destroy_triangle(poly);
  // unload the triangle library
  dlclose(triangle);

  exit(EXIT_SUCCESS);
}

#else

int main() { return 0; }

#endif
